from . import paper_blueprint
from ..utils.response_util import response
from ..utils.exception import APIException
from ..utils.error_code import *
from ..utils.check import *
from ..models import *

from flask import request, session
import json
from sqlalchemy import or_
import random
from math import ceil


@paper_blueprint.route("/", methods=["GET", "POST"])
def main():
    return "Paper"


@paper_blueprint.errorhandler(APIException)
def error(e):
    return APIException.to_dict(e)


@paper_blueprint.route("/add", methods=["POST"])
@user_is_login
@check_user_type_3
def paper_add():
    """
    添加试卷
    :return:
    """
    data = get_data()
    username = session.get("username")
    paper_question = data.get("paperQuestion")

    for question_ in paper_question:
        question_id = 0
        for question in question_.keys():
            if "question" in question:
                question_id = question_[question]
        if question_id == 0:
            raise APIException(NO_QUESTION_EXISTS)
        question = Question.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS, {"question_id": question_id})
    # 生成 paper
    paper = Paper(json.dumps(paper_question), username)

    try:
        db.session.add(paper)
        db.session.commit()
        paper_id = paper.paper_id
    except:
        db.session.rollback()
    finally:
        db.session.close()

    return response(200, "Add Paper Success", {"paperID": paper_id})


@paper_blueprint.route("/update", methods=["POST"])
@user_is_login
@check_user_type_3
def paper_update():
    """
    修改试卷
    :return:
    """
    data = get_data()
    username = session.get("username")
    paper_id = data.get("paperId")
    paper_question = data.get("paperQuestion")
    new_data = dict()

    if paper_question is None:
        raise APIException(NO_DATA_FOUND)
    for question_ in paper_question:
        question_id = 0
        for question in question_.keys():
            if "question" in question:
                question_id = question_[question]
        if question_id == 0:
            raise APIException(NO_QUESTION_EXISTS)
        question = Question.query.filter_by(question_id=question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS, {"question_id": question_id})

    new_data["paper_question"] = json.dumps(paper_question)
    user = User.query.filter(User.username == username).first()
    paper = Paper.query.filter(Paper.paper_id == paper_id).first()
    if paper is None:
        raise APIException(NO_PAPER_EXISTS)
    if paper.paper_add_user_id != int(username) and user.type == 3:
        raise APIException(INSUFFICIENT_USER_PERMISSION)

    res = Paper.query.filter_by(paper_id=paper_id).update(new_data)
    db.session.commit()
    db.session.close()

    if res == 1:
        return response(200, "Update Paper Success", {"paperId": paper_id})
    else:
        raise APIException(UPDATE_ERROR)


@paper_blueprint.route("/delete", methods=["GET", "POST"])
@user_is_login
@check_user_type_3
def paper_delete():
    """
    删除试卷
    :return:
    """
    data = get_data()
    username = session.get("username")
    paper_id = data.get("paperId")
    # 判断 user 权限
    user = User.query.filter(User.username == username).first()
    # 删除 Paper
    paper = Paper.query.filter(Paper.paper_id == paper_id).first()
    if paper is None:
        raise APIException(NO_PAPER_EXISTS)
    if user.user_type == 3 and paper.paper_add_user_id != user.username:
        raise APIException(INSUFFICIENT_USER_PERMISSION)

    res = Paper.query.filter_by(paper_id=paper_id).delete()
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(DELETE_ERROR)

    finally:
        db.session.close()

    if res == 1:
        return response(200, "Delete Paper Success", {"paper_id": paper_id})
    else:
        raise APIException(DELETE_ERROR)


@paper_blueprint.route("/search", methods=["POST"])
@user_is_login
def paper_search():
    """
    查看试卷
    :return:
    """
    data = get_data()
    paper_id = data.get("paperId")
    username = session.get("username")
    r = list()

    paper = Paper.query.filter(Paper.paper_id == paper_id).first()
    if paper is None:
        raise APIException(NO_PAPER_EXISTS)
    user = User.query.filter(User.username == username).first()
    if user is None:
        raise APIException(USERNAME_NOT_EXISTS)

    for question_and_score in json.loads(paper.paper_question):
        question_id = 0
        for question in question_and_score.keys():
            if "question" in question:
                question_id = question_and_score[question]
        if question_id == 0:
            raise APIException(NO_QUESTION_EXISTS)
        tmp = dict()
        question = Question.query.filter(Question.question_id == question_id).first()
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        question_type = question.question_type
        # 填空题
        if question_type == 1:
            question = QuestionOfFillBlank.query.filter_by(question_id=question_id).first()
        # 选择题
        elif question_type == 2:
            select = list()
            question = QuestionOfSelect.query.filter_by(question_id=question_id).first()
            wrong_answer = json.loads(question.wrong_answer)
            right_answer = question.right_answer
            print(wrong_answer)
            print(right_answer)
            select.extend(wrong_answer)
            select.append(right_answer)
            random.shuffle(select)
            tmp["select"] = select
            # tmp["A"] =
        # 判断题
        elif question_type == 3:
            question = QuestionOfJudge.query.filter_by(question_id=question_id).first()
        # 程序填空题
        elif question_type == 4:
            question = QuestionOfProgramFillBlank.query.filter_by(question_id=question_id).first()
            tmp["input_format"] = question.input_format[: 3]
            tmp["output_format"] = question.output_format[: 3]
        # 程序改错题
        elif question_type == 5:
            question = QuestionOfProgramModify.query.filter_by(question_id=question_id).first()
            tmp["input_format"] = question.input_format[: 3]
            tmp["output_format"] = question.output_format[: 3]
        # 编程题
        elif question_type == 6:
            question = QuestionOfProgram.query.filter_by(question_id=question_id).first()
            tmp["input_format"] = question.input_format[: 3]
            tmp["output_format"] = question.output_format[: 3]
        if question is None:
            raise APIException(NO_QUESTION_EXISTS)
        tmp["question_title"] = question.question_title
        tmp["relate_course"] = question.relate_course_id
        tmp["question_description"] = question.question_description
        tmp["question_type"] = question_type

        r.append(tmp)

    return response(200, "Search Paper Success", r)


@paper_blueprint.route("/list", methods=["POST"])
@user_is_login
def paper_list():
    """
    试卷列表
    :return:
    """
    try:
        current_page = int(request.args.get("currentPage"))
    except:
        current_page = 1
    data_per_page = 10
    username = session.get("username")
    r = list()
    user = User.query.filter_by(username=username).first()
    if user is None:
        raise APIException(USERNAME_NOT_EXISTS)

    if user.user_type == 1:
        papers = Paper.query.filter(Paper.status == 1).order_by(-Paper.create_time).all()
    elif user.user_type == 2:
        papers = Paper.query.filter(or_(Paper.status == 1, Paper.paper_add_user_id == user.username)).order_by(-Paper.create_time).all()
    else:
        papers = Paper.query.order_by(-Paper.create_time).all()
    if papers is None:
        raise APIException(NO_PAPER_EXISTS)

    list_len = len(papers)
    for paper in papers:
        tmp = dict()
        tmp["paper_id"] = paper.paper_id
        tmp["paper_add_user_id"] = paper.paper_add_user_id
        tmp["create_time"] = str(paper.create_time)
        r.append(tmp)

    max_page_num = ceil(list_len / data_per_page)

    ret = {
        "currentPage": current_page,
        "maxPageNum": max_page_num,
        "num": list_len,
        "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
    }

    return response(200, "Query Paper List Success", ret)
